package org.springboot.jdbctemplate.service.impl;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springboot.jdbctemplate.config.TransactionConfig;
import org.springboot.jdbctemplate.dao.IAccountDAO;
import org.springboot.jdbctemplate.dao.entity.Account;
import org.springboot.jdbctemplate.service.IAccountService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;

@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class AccountServiceImpl implements IAccountService {
	
	private static final Logger logger = LoggerFactory.getLogger(AccountServiceImpl.class);
	
	@Autowired
    IAccountDAO accountDAO;
	
    @Override
    public int add(Account account) {
        return accountDAO.add(account);
    }

    @Override
    public int update(Account account) {
        return accountDAO.update(account);
    }

    @Override
    public int delete(int id) {
        return accountDAO.delete(id);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDAO.findAccountById(id);
    }

    @Override
    public List<Account> findAccountList() {
        return accountDAO.findAccountList();
    }

	@Autowired
	private TransactionConfig txConfig;

	@Override
	public void tx() {
		declarativeTxManager();
		declarativeTxTemplate();
		try {
			// 这里就相当于使用了 this.programmaticTx(); 如果使用的是本地对象的方法，没有用到 spring 容器，就无法触发 AOP，导致事务失效
	        ((AccountServiceImpl) AopContext.currentProxy()).programmaticTx();
		} catch (Exception e) {
			logger.error("fail" ,e);
        }   
	}

	private void declarativeTxManager() {
		// 事务基础信息 超时时间、隔离级别、传播属性等
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // 设置传播行为属性， 默认事务级别。 当前无事务则新建事务，已有事务则加入事务
        def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
        // 获得事务状态
        TransactionStatus status = txConfig.getTxManager().getTransaction(def);
        try {
        	// 业务操作
        	businessOperate("declarativeTxManager");
            // 提交事务
            txConfig.getTxManager().commit(status);
        } catch (Exception e) {
            // 提交事务回滚
        	txConfig.getTxManager().rollback(status);
        }
	}

	private void declarativeTxTemplate() {
		txConfig.getTxTemplate().execute(new TransactionCallback<String>() {
            @Override
            public String doInTransaction(TransactionStatus transactionStatus) {
                try {
                	// 业务操作
                    businessOperate("declarativeTxTmpl");
                    return "success";
                } catch (Exception e) {
                	// 提交事务回滚
                    transactionStatus.setRollbackOnly();
                    return "fail";
                }
            }
        });
	}

	@Transactional(rollbackFor = Exception.class)
	public void programmaticTx() {
		businessOperate("programmaticTx");
	}

	private void businessOperate(String name) {
		Account account = new Account();
		account.setName(name);
		account.setMoney(System.currentTimeMillis());
		accountDAO.add(account);
        @SuppressWarnings("unused")
		int i = 1 / 0;
	}

}
